﻿//-----------------------------------------------------------------------
// <copyright file="DoNotUseBannedApis.cs">
//     Copyright (c) Nicole Calinoiu. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;

using Microsoft.FxCop.Sdk;
using Microsoft.VisualStudio.CodeAnalysis.Extensibility;

using Bordecal.FxCop.Rules.Usage.Configuration;
using Bordecal.FxCop.Sdk;

namespace Bordecal.FxCop.Rules.Usage
{
	/// <summary>
	/// Rule that verifies that banned APIs are not used.
	/// </summary>
	internal sealed class DoNotUseBannedApis : ConfigurableIntrospectionRule<DoNotUseBannedApisConfiguration>
	{
		#region Constructors

		/// <summary>
		/// Initializes a new instance of the <see cref="DoNotUseBannedApis"/> class.
		/// </summary>
		public DoNotUseBannedApis()
			: base(RuleDescriptorFactory.CreateSingleResolutionDescriptor<DoNotUseBannedApis>(
				RuleCategory.Usage,
				"Do not use banned APIs",
				"Do not use APIs that have been banned by your organization.",
				95,
				FixCategories.DependsOnFix,
				MessageLevel.Error,
				"Do not use the banned {0} {1}."))
		{
		}

		#endregion

		#region Methods

		/// <summary>
		/// Verifies compliance of a type member with the implemented rule.
		/// </summary>
		/// <param name="member">The target member.</param>
		/// <returns>A collection of found problems.</returns>
		public override ProblemCollection Check(Member member)
		{
			Method method = member as Method;
			if (method != null)
			{
				this.Visit(method.Body);
			}

			return this.Problems;
		}

		/// <summary>
		/// Visits a <see cref="MemberBinding"/>.
		/// </summary>
		/// <param name="memberBinding">The <see cref="MemberBinding"/>.</param>
		public override void VisitMemberBinding(MemberBinding memberBinding)
		{
			if (memberBinding == null)
			{
				throw new ArgumentNullException("memberBinding");
			}

			base.VisitMemberBinding(memberBinding);

			string name = memberBinding.BoundMember.DeclaringType.FullName;
			if (this.CurrentConfiguration.BannedTypes.Any(n => n.Equals(name, StringComparison.Ordinal)))
			{
				this.AddIdentifiedProblem(memberBinding, name, name, "type");
			}
			else
			{
				name = memberBinding.BoundMember.FullName;
				if (this.CurrentConfiguration.BannedMembers.Any(n => n.Equals(name, StringComparison.Ordinal)))
				{
					this.AddIdentifiedProblem(memberBinding, name, name, "member");
				}
			}
		}

		#endregion
	}
}